package com.shuhe.handler;

import com.alibaba.fastjson.JSONObject;
import com.shuhe.common.MyDateUtils;
import com.shuhe.domain.alarm.TopicMessage;
import com.shuhe.domain.api.ApiResponseBody;
import com.shuhe.metastore.DBAppSql;
import com.shuhe.metastore.MqttClientV5;
import org.apache.log4j.Logger;
import org.eclipse.paho.mqttv5.client.MqttClient;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import static com.shuhe.common.CommonFunction.*;
import static com.shuhe.common.EncryptUtils.encrypt;
import static com.shuhe.handler.ServiceDetail.decryptToken;
import static com.shuhe.handler.ServiceDetail.encryptToken;
import static com.shuhe.thread.MqttReceiveThread.writeErrorMessage;


public class AlarmHandler extends HttpServlet {

    private static Logger logger = Logger.getLogger(AlarmHandler.class);

    public static ArrayList<TopicMessage> testSubjectMessages = new ArrayList<TopicMessage>();
    public static ArrayList<String> stopTopics = new ArrayList<String>();
    public static ArrayList<MqttClient> mqttClients = new ArrayList<MqttClient>();

    @Override
    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp = setResponse(resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Connection appConn = null;
        try {
            resp = setResponse(resp);
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("application/json");

            String bodyStr = readAsChars(req);
            JSONObject bodyJson = JSONObject.parseObject(bodyStr);

            appConn = DBAppSql.connect();
            String operateType = bodyJson.getString("operateType");
            if ("testConnection".equals(operateType)) {
                String sqlResp = testConnection(bodyJson);
                resp.getWriter().write(sqlResp);
            }
            if ("getSampleData".equals(operateType)) {
                String sqlResp = getSampleData(bodyJson);
                resp.getWriter().write(sqlResp);
            }
            if ("startReceive".equals(operateType)) {
                String sqlResp = startReceive(bodyJson, false);
                resp.getWriter().write(sqlResp);
            }
            if ("refreshMessage".equals(operateType)) {
                String sqlResp = refreshMessage(bodyJson);
                resp.getWriter().write(sqlResp);
            }
            if ("stopReceive".equals(operateType)) {
                String sqlResp = stopReceive(bodyJson);
                resp.getWriter().write(sqlResp);
            }
            if ("login".equals(operateType)) {
                String sqlResp = login(bodyJson, appConn);
                resp.getWriter().write(sqlResp);
            }
            if ("api".equals(operateType)) {
                String sqlResp = api(bodyJson, appConn);
                resp.getWriter().write(sqlResp);
            }
            if ("testPublish".equals(operateType)) {
                String sqlResp = testPublish(bodyJson);
                resp.getWriter().write(sqlResp);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.info(ex.getMessage());
            resp.getWriter().write(returnFail(ex.getMessage()));
        } finally {
            closeDb(appConn);

        }
    }


    public static String testPublish(JSONObject bodyJson) throws Exception {
        String broker_ip = bodyJson.getString("broker_ip");
        String port = bodyJson.getString("port");
        String client_id = bodyJson.getString("client_id");
        String username = bodyJson.getString("username");
        String password = bodyJson.getString("password");
        String topic = bodyJson.getString("sub_topic");
        String brokerUrl = "tcp://" + broker_ip + ":" + port;
        MqttClientV5.testPublish(brokerUrl, client_id, username, password, topic);
        return getResultJson("200", "success").toJSONString();
    }

    public static void writeApiError(String errorMsg, Connection appConn, String login_name, String service_id,
                                     JSONObject bodyJson)
            throws Exception {
        String bodyStr = bodyJson.toJSONString().replaceAll("'", "''");
        String sql = "insert into sys_service_log(id, login_name, req_time, service_id, res_body, res_status, " +
                "err_detail, res_time, req_body) values('" + getUUID() + "', '" + login_name
                + "', now(), " + "'" + service_id + "', '" + bodyStr + "', '201', '" + errorMsg + "', now(), '')";
        DBAppSql.execSql(appConn, sql);
    }

    public static String apiError(String msg, Connection appConn, String login_name, String service_id,
                                  JSONObject bodyJson) throws Exception{
        writeApiError(msg, appConn, login_name, service_id, bodyJson);
        writeErrorMessage(appConn, msg, "msg_type_04");
        return returnFail(msg);
    }

    public static String api(JSONObject bodyJson, Connection appConn) throws Exception {
        String startTime = MyDateUtils.getNowDate();
        String token = bodyJson.getString("token");
        String login_name = decryptToken(token);
        String service_id = bodyJson.getString("serviceId");
        if (service_id == null || service_id.equals("")) {
            String msg = "必须传递serviceId参数";
            return apiError(msg, appConn, login_name, service_id, bodyJson);

        }
        String sql = "select * from sys_user where login_name = '" + login_name + "'";
        ResultSet rs = DBAppSql.querySql(appConn, sql);
        if (!rs.next()) {
            String msg = "token错误";
            return apiError(msg, appConn, login_name, service_id, bodyJson);
        }
        sql = "select * from sys_service_register where id = '" + service_id + "'";
        rs = DBAppSql.querySql(appConn, sql);
        if (!rs.next()) {
            String msg = "serviceId错误";
            return apiError(msg, appConn, login_name, service_id, bodyJson);
        }
        String tableName = rs.getString("table_name");
        sql = "select count(*) from " + tableName;

        String whereCondition = bodyJson.getString("whereCondition");
        if (whereCondition != null && whereCondition.length() > 0) {
            sql = sql + " where " + whereCondition;
        }

        int recordNum = 0;
        rs = DBAppSql.querySql(appConn, sql);
        if (rs.next()) {
            recordNum = rs.getInt(1);
        }

        String columnName = bodyJson.getString("columnName");
        if (columnName != null && columnName.length() > 0) {
            sql = "select " + columnName + " from " + tableName;
        } else {
            sql = "select * from " + tableName;
        }

        if (whereCondition != null && whereCondition.length() > 0) {
            sql = sql + " where " + whereCondition;
        }
        String orderColumn = bodyJson.getString("orderColumn");
        if (orderColumn != null && orderColumn.length() > 0) {
            sql = sql + " order by " + orderColumn;
        }
        String rows = bodyJson.getString("rows");
        String offset = bodyJson.getString("offset");
        if (rows != null && rows.length() > 0 && offset != null && offset.length() > 0) {
            sql = sql + " limit " + rows + " offset " + offset;
        }
        rs = DBAppSql.querySql(appConn, sql);
        ApiResponseBody body = new ApiResponseBody();
        body.setStatus("200");
        body.setMsg("查询成功");
        body.setTotalRowNumber(String.valueOf(recordNum));
        body.setData(getResultSet(rs));
        String res_body = JSONObject.toJSONString(body);

        String endTime = MyDateUtils.getNowDate();
        sql = "insert into sys_service_log(id, login_name, req_time, service_id, res_body, res_status, " +
                "err_detail, res_time, req_body) values('" + getUUID() + "', '" + login_name
                + "', '" + startTime + "', " + "'" + service_id + "', '" +
                bodyJson.toJSONString().replaceAll("'", "''") + "', '200', '', " +
                "'" + endTime + "', '" + res_body + "')";
        DBAppSql.execSql(appConn, sql);
        return res_body;
    }

    public static String login(JSONObject bodyJson, Connection appConn) throws Exception {
        String login_name = bodyJson.getString("login_name");
        String password = bodyJson.getString("password");
        String sql = "select * from sys_user where login_name = '" + login_name + "' and password = '" + password + "'";
        ResultSet rs = DBAppSql.querySql(appConn, sql);
        ArrayList<Object> datas = getResultSet(rs);
        JSONObject resultJson = getResultJson("200", "success");
        resultJson.put("data", datas);
        if (datas.size() > 0) {
            resultJson.put("token", encryptToken(login_name));
        }
        return resultJson.toJSONString();
    }

    public static String refreshMessage(JSONObject bodyJson) throws Exception {
        String topic = bodyJson.getString("topic");
        List<TopicMessage> result = new ArrayList<>();
        for (TopicMessage message : testSubjectMessages) {
            if (topic.equals(message.getTopic())) {
                result.add(message);
            }
        }
        JSONObject resultJson = getResultJson("200", "success");
        resultJson.put("data", result);
        return resultJson.toJSONString();
    }

    public static String getSampleData(JSONObject bodyJson) throws Exception {
        return startReceive(bodyJson, true);
    }

    public static String startReceive(JSONObject bodyJson, boolean isAutoClose) throws Exception {
        String broker_ip = bodyJson.getString("broker_ip");
        String port = bodyJson.getString("port");
        String client_id = bodyJson.getString("client_id");
        String username = bodyJson.getString("username");
        String password = bodyJson.getString("password");
        String topic = bodyJson.getString("topic");
        String brokerUrl = "tcp://" + broker_ip + ":" + port;
        testSubjectMessages.removeIf(message -> topic.equals(message.getTopic()));
        if (stopTopics.contains(topic)) {
            stopTopics.remove(topic);
        }
        Thread client1Thread = new Thread(() -> {
            try {
                MqttClientV5.testSubsription(brokerUrl, client_id, username, password, topic, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        client1Thread.start();
        return getResultJson("200", "success").toJSONString();
    }

    public static String stopReceive(JSONObject bodyJson) throws Exception {
        String topic = bodyJson.getString("topic");
        if (!stopTopics.contains(topic)) {
            stopTopics.add(topic);
        }
        return getResultJson("200", "success").toJSONString();
    }

    public static String testConnection(JSONObject bodyJson) throws Exception {
        String protocol = bodyJson.getString("protocol");
        String broker_ip = bodyJson.getString("broker_ip");
        String port = bodyJson.getString("port");
        String client_id = bodyJson.getString("client_id");
        String username = bodyJson.getString("username");
        String password = bodyJson.getString("password");
        String brokerUrl = "tcp://" + broker_ip + ":" + port;

        MqttClientV5.testConnect(brokerUrl, client_id, username, password);
        return getResultJson("200", "success").toJSONString();
    }


}
